﻿using System;
using System.Collections.Generic;

public class FsmControllerBase<T> : IFsmController<T>
{
    protected IEqualityComparer<T> dicComparer;
    
    public FsmStateBase<T> currentState = null;
    public Dictionary<T, FsmStateBase<T>> allStates = null;

    public T CurrentStateType
    {
        get
        {
            if (currentState != null)
            {
                return currentState.StateType;
            }
            return default(T);
        }
    }
    
    public virtual void InitState()
    {
        InitState(null);
    }
    
    public virtual void InitState(IEqualityComparer<T> dicComparer = null)
    {
        var type = typeof(T);
        if (typeof(ValueType).IsAssignableFrom(typeof(T)) && !typeof(IEquatable<T>).IsAssignableFrom(typeof(T)) && dicComparer == null)
        {
            GLog.Error("{0} 是没有实现IEquatable值类型, 需要一个IEqualityComparer，避免GC~！~！", type.ToString());
            dicComparer = EqualityComparer<T>.Default;
        }

        this.dicComparer = dicComparer;
        allStates = new Dictionary<T, FsmStateBase<T>>();
    }
        
    public Dictionary<T, FsmStateBase<T>> GetStateList()
    {
        return allStates;
    }
    
    public void AddState(T stateType, FsmStateBase<T> state)
    {
        if (allStates.ContainsKey(stateType))
        {
            allStates.Remove(stateType);
        }
        allStates[stateType] = state;
    }

    public IFsmState<T> GetState(T stateType)
    {
        if (allStates.TryGetValue(stateType, out var result))
        {
            return result;
        }
        return null;
    }

    public virtual bool SwitchState(T stateType, Object data = null)
    {
        GLog.Debug("Leave state " + CurrentStateType);
        if (currentState != null)
        {
            currentState.Leave();
            currentState = null;
        }

        GLog.Debug("Enter state " + stateType);
        if(allStates.TryGetValue(stateType, out currentState))
        {
            currentState.Enter(data);
        }

        return true;
    }

    public virtual void UpdateState(float deltaTime)
    {
        if(currentState != null)
        {
            currentState.Update(deltaTime);
        }
    }
    
    public IFsmState<T> GetCurrentState()
    {
        return currentState;
    }

    public bool IsInXState(T stateType)
    {
        return dicComparer.Equals(CurrentStateType, stateType);
    }
    
    public bool IsInXState<State, T>() where State : FsmStateBase<T>
    {
        if (currentState == null) return false;
        return currentState is State;
    }
}